import cv2
import numpy as np
import matplotlib.pyplot as plt
import os
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置为黑体  
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
# 读取原图
img = cv2.imread('hanzi1.jpg')
# 读取彩色图像
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 

# 将图像转换为灰度图像
gray_img = cv2.cvtColor(rgb_img, cv2.COLOR_RGB2GRAY)
binary_img = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV)[1]  

# 创建结构元素
kernel = np.ones((3, 3), np.uint8)  
eroded_img = cv2.erode(binary_img, kernel, iterations=3)

median_filtered_img = cv2.medianBlur(eroded_img, 5)
dilated_img = cv2.dilate(median_filtered_img, kernel,iterations=3) 

# 进行闭运算
closed_img = cv2.morphologyEx(dilated_img, cv2.MORPH_CLOSE, kernel,iterations=30)

#Canney
img_blur = cv2.GaussianBlur(closed_img,(3,3), 0) #高斯滤波
edges_with_blur = cv2.Canny(img_blur, 50,200)

# 得到图像轮廓列表
contours, _ = cv2.findContours(edges_with_blur, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# 复制图像以绘制边界框
img_copy = rgb_img.copy()

# 遍历轮廓列表
for c in contours:
    perimeter = cv2.arcLength(c, True)
    
    x, y, w, h = cv2.boundingRect(c)
    cv2.rectangle(img_copy, (x, y), (x + w, y + h), (0, 255, 0), 2)

    # 根据周长阈值筛选并绘制边界框
    if perimeter > 100:
        cv2.rectangle(img_copy, (x, y), (x + w, y + h), (0, 255, 0), 2)

# 创建包含7个子图的画布
fig, ax = plt.subplots(1, 7, figsize=(30, 15))

ax[0].imshow(gray_img, cmap='gray')
ax[0].set_title(f"原图灰度图", size=6)
ax[0].axis('off')

ax[1].imshow(binary_img, cmap='gray')
ax[1].set_title(f"进行全局阈值处理，生成二值化图", size=6)
ax[1].axis('off')

ax[2].imshow(eroded_img, cmap='gray')
ax[2].set_title(f"应用腐蚀操作，去除噪点", size=6)
ax[2].axis('off')

ax[3].imshow(dilated_img, cmap='gray')
ax[3].set_title(f"应用膨胀操作，突出图像特征，中值滤波去除小白点", size=6)
ax[3].axis('off')

ax[4].imshow(closed_img, cmap='gray')
ax[4].set_title(f"进行闭运算，填充闭合区域", size=6)
ax[4].axis('off')

ax[5].imshow(edges_with_blur, cmap='gray')
ax[5].set_title(f"Canney边缘检测", size=6)
ax[5].axis('off')

ax[6].imshow(img_copy, cmap='gray')
ax[6].set_title(f"识别结果", size=6)
ax[6].axis('off')

# 调整子图布局
plt.tight_layout()
# 显示图形
plt.show()

if not os.path.exists('chars'):
    os.makedirs('chars')

# 裁剪并保存每个字的图像
for i, c in enumerate(contours):
    perimeter = cv2.arcLength(c, True)
    if perimeter > 325:
        approx = cv2.approxPolyDP(c, 0.02 * perimeter, True)
        x, y, w, h = cv2.boundingRect(approx)
        char_img = img[y:y+h, x:x+w]
        cv2.imwrite(f'chars/chars_{i}.png', char_img)



